﻿using DeHeng_Mes.Constant;
using DeHeng_Mes.Dao;
using DeHeng_Mes.Dao.PlcDao;
using DeHeng_Mes.Model;
using DeHeng_Mes.Model.Boss;
using DeHeng_Mes.Model.BossModel;
using DeHeng_Mes.Model.ConfigModel;
using DeHeng_Mes.Model.OrderSingleton;
using DeHeng_Mes.Model.Singleton;
using DeHeng_Mes.Model.Table;
using DeHeng_Mes.Utils;
using Newtonsoft.Json;
using NPOI.SS.Formula.Functions;
using Org.BouncyCastle.Asn1.Pkcs;
using S7.Net;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Controls.Primitives;
using System.Windows.Shapes;
using Path = System.IO.Path;

namespace DeHeng_Mes.Service
{
    public class PlcServicees
    {
        #region 成员实例
        PlcDao plcDao = new PlcDao();
        ProductionPowerDao productionPowerDao = new ProductionPowerDao();
        List<PlcOrderConfigModel> readPlcList = PlcOrderConfigModelList.ReadPlcList;
        #endregion

        public void GetPowerAndProdution(bool isTimer)
        {
            // 检查连接状态并查询工单
            foreach (var item in PlcConnectionManager.plcContainer)
            {
                // 未连接跳出本层
                if (!item.isConnected)
                    continue;

                // 获取Plc数据
                Dictionary<object, Type> dictionary = MappingTable.PlcMapping(item.plc, item.name);

                // 获取当前日期
                DateTime currentDate = DateTime.Now;

                // 获取天
                DateTime previousDate = isTimer ? currentDate.AddDays(-1) : currentDate;

                string day = previousDate.Day.ToString();

                // 获取当前年月日
                string date = $"{previousDate.Year}{previousDate.Month:D2}{previousDate.Day:D2}";

                // 判断当前plcName，执行不同方法
                switch (item.name)
                {
                    case "DOOR-01":
                        break;
                    case "DOOR-02":
                        Dictionary<string, string> keyValuePairs = new Dictionary<string, string>();

                        // 执行当日产量采集
                        keyValuePairs.Add("L", plcDao.GetStringFieldValue(dictionary, "Production", "LRealTimeProduction"));
                        keyValuePairs.Add("R", plcDao.GetStringFieldValue(dictionary, "Production", "RRealTimeProduction"));

                        // 存入当天产量数据
                        foreach (var production in keyValuePairs)
                        {
                            // 判断产量数据是否保存
                            if (productionPowerDao.ProductionIsSave(item.name, date, production))
                                // 执行更新操作
                                productionPowerDao.UpdateProduction(item.name, date, production);
                            else
                                //执行插入操作
                                productionPowerDao.ProductionSave(item.name, date, production);
                        }
                        break;
                }

                // 执行当日能耗采集
                string power = plcDao.GetStringFieldValue(dictionary, "Power", "RealTimePower");

                // 存入当天能耗数据
                if (!string.IsNullOrEmpty(power))
                {
                    // 判断能耗数据是否保存
                    if (productionPowerDao.PowerIsSave(item.name, date, power))
                        // 执行更新操作
                        productionPowerDao.UpdatePower(item.name, date, power);
                    else
                        //执行插入操作
                        productionPowerDao.PowerSave(item.name, date, power);
                }
            }
        }

        /// <summary>
        /// 0点监控
        /// </summary>
        public async Task Timer()
        {
            Tools.ProduceLogText("零点监控线程启动成功！");

            while (true)
            {
                // 获取当前时间
                DateTime now = DateTime.Now;

                // 判断是否为凌晨0点
                // 判断是否为凌晨0点
                if (now.Hour == 0 && now.Minute == 0 && now.Second == 0)
                {
                    GetPowerAndProdution(true);
                }
                await Task.Delay(200);
            }
        }

        /// <summary>
        /// 读取CSV文件
        /// </summary>
        /// <returns></returns>
        public async Task ReadCSVData()
        {
            Tools.ProduceLogText("拉铆数据轮询线程启动成功!");

            OrderDao orderDao = new OrderDao();

            Dictionary<string, string> dic = new Dictionary<string, string>()
                    {
                        { "CLINCH_LEFT","192.168.12.55"},
                        { "CCD","192.168.13.181"},
                        { "RIVET_LEFT","192.168.12.209"},
                        { "RIVET_RIGHT","192.168.12.210"},
                        { "RIVET_PLC2","192.168.13.209"},
                        /*{ "CLINCH_RIGHT","192.168.12.55"},*/
                    };

            while (true)
            {
                foreach (var filePaths in dic)
                {
                    try
                    {
                        await CsvConnection(filePaths.Key, filePaths.Value, orderDao);
                    }
                    catch (Exception ex)
                    {
                        Tools.ProduceLogText($"[{filePaths.Key}:{filePaths.Value}]读取并保存CSV数据发生异常：原因是：{ex.Message}");
                    }

                    await Task.Delay(5000);
                }
            }
        }

        /// <summary>
        /// Csv文件读取
        /// </summary>
        /// <param name="operation"></param>
        /// <param name="path"></param>
        /// <param name="orderDao"></param>
        private async Task CsvConnection(string operation, string pathIp, OrderDao orderDao)
        {
            switch (operation)
            {
                case "RIVET_LEFT":
                    await RivetConnection(pathIp, orderDao);
                    break;
                case "RIVET_RIGHT":
                    await RivetConnection(pathIp, orderDao);
                    break;
                case "RIVET_PLC2":
                    await RivetConnection(pathIp, orderDao);
                    break;
                case "CLINCH_LEFT":
                    await ClinchConnection(pathIp, orderDao);
                    break;
                case "CLINCH_RIGHT":
                    await ClinchConnection(pathIp, orderDao);
                    break;
                case "CCD":
                    await CCDConnection(pathIp, orderDao);
                    break;
            }
        }

        /// <summary>
        /// CCD文件读取
        /// </summary>
        /// <param name="pathIp"></param>
        /// <param name="orderDao"></param>
        private async Task CCDConnection(string pathIp, OrderDao orderDao)
        {
            foreach (var LR in new[] { "R", "L" })
            {
                var now = DateTime.Now;

                string directory = Path.Combine(
                    $@"\\{pathIp}\csv",
                    LR,
                    now.ToString("yyyy"),
                    now.ToString("MM"),
                    now.ToString("dd")
                );

                if (Directory.Exists(directory))
                {

                    try
                    {
                        // 获取目录下所有CSV文件路径
                        string[] csvFiles = Directory.GetFiles(directory, "*.csv");

                        foreach (string filePath in csvFiles)
                        {
                            if (filePath.Contains("_Save"))
                                continue;

                            // 提取文件名和扩展名
                            string fileName = Path.GetFileNameWithoutExtension(filePath);
                            string extension = Path.GetExtension(filePath); // 如 ".csv"

                            // 构建新文件名：原文件名 + "_Save" + 扩展名
                            string newFileName = $"{fileName}_Save{extension}";
                            string newFilePath = Path.Combine(Path.GetDirectoryName(filePath), newFileName);

                            // 调用方法读取文件数据
                            Dictionary<string, string[]> csvData = await CsvReaderHelper.ReadCsv(filePath, "测点名称");

                            List<TraceCCD> traceCCDs = new List<TraceCCD>();

                            string[] parts = fileName.Split(new[] { '\\' }, StringSplitOptions.RemoveEmptyEntries);

                            string code = parts[parts.Length - 1].Split('_')[0];

                            string station = "Op180" + LR;

                            // 循环存储
                            for (int i = 0; i <= csvData["测点名称"].Length - 1; i++)
                            {
                                // 实例化存储类
                                TraceCCD traceCCD = new TraceCCD();

                                traceCCD.TraceId = code;

                                traceCCD.Station = station;

                                traceCCD.Result = csvData["Result"][i];

                                traceCCD.PointName = csvData["测点名称"][i];

                                traceCCDs.Add(traceCCD);
                            }

                            Tools.ProduceLogText($"成功保存{csvData["测点名称"].Length}条CCD数据，关联码为[{code}]");

                            try
                            {
                                // 重命名文件（如果已存在则跳过或覆盖）
                                if (!File.Exists(newFilePath))
                                {
                                    orderDao.SaveCCDData(traceCCDs, code);

                                    File.Move(filePath, newFilePath);

                                    //推送CCD工艺数据
                                    _ = Task.Run(() => { ViewService.InsertLineMesData(code, station, traceCCDs); });
                                }
                                else
                                {
                                    Tools.ProduceLogTextError($"文件已存在，跳过: {newFileName}");

                                    File.Delete(filePath);
                                }
                            }
                            catch (IOException ex)
                            {
                                Tools.ProduceLogTextError($"标签打入失败: {ex.Message}");
                            }
                        }
                    }
                    catch (DirectoryNotFoundException)
                    {
                        Tools.ProduceLogTextError($"CCD数据文件目录不存在: {directory}");
                    }
                    catch (UnauthorizedAccessException)
                    {
                        Tools.ProduceLogTextError("CCD数据文件没有访问权限，请检查凭据。");
                    }
                    catch (Exception ex)
                    {
                        Tools.ProduceLogTextError($"CCD数据文件读取发生错误: {ex.Message}");
                    }
                }
            }
        }

        /// <summary>
        /// 压铆文件读取
        /// </summary>
        /// <param name="pathIp"></param>
        /// <param name="orderDao"></param>
        private async Task ClinchConnection(string pathIp, OrderDao orderDao)
        {
            // 初始化日期
            string date = $"{DateTime.Now.ToString("yyyy")}{DateTime.Now.ToString("MM")}{DateTime.Now.ToString("dd")}";

            // 初始化文件夹路径
            string directory = $@"\\{pathIp}\ym\before\Data_info\{date}\{date}";

            if (Directory.Exists(directory))
            {

                try
                {
                    // 获取目录下所有CSV文件路径
                    string[] csvFiles = Directory.GetFiles(directory, "*.csv");

                    foreach (string filePath in csvFiles)
                    {
                        if (filePath.Contains("_Save"))
                            continue;

                        // 提取文件名和扩展名
                        string fileName = Path.GetFileNameWithoutExtension(filePath);
                        string extension = Path.GetExtension(filePath); // 如 ".csv"

                        // 构建新文件名：原文件名 + "_Save" + 扩展名
                        string newFileName = $"{fileName}_Save{extension}";
                        string newFilePath = Path.Combine(Path.GetDirectoryName(filePath), newFileName);

                        // 调用方法读取文件数据
                        Dictionary<string, string[]> csvData = await CsvReaderHelper.ReadCsv(filePath, "零件二维码");

                        List<TraceClinch> traceClinchs = new List<TraceClinch>();

                        // 实例化存储类
                        TraceClinch traceClinch = new TraceClinch();

                        // 循环存储
                        for (int i = 0; i <= csvData["零件二维码"].Length - 1; i++)
                        {
                            traceClinch.Result = csvData["单次结果"][i];

                            traceClinch.DataTime = $"{csvData["日期"][i]} {csvData["时间"][i]}";

                            traceClinch.Pressure = csvData["压力 "][i];

                            traceClinch.PressureMax = csvData["压力上限"][i];

                            traceClinch.PressureMin = csvData["压力下限 "][i];

                            traceClinch.Displacement = csvData["位移"][i];

                            traceClinch.DisplacementMax = csvData["位移上限"][i];

                            traceClinch.DisplacementMin = csvData["位移下限"][i];

                            traceClinch.TraceId = csvData["零件二维码"][i];

                            traceClinch.PointNo = csvData["点位编号"][i];

                            traceClinch.PointCount = csvData["点位计数 "][i];

                            traceClinch.ToolNo = csvData["程序号"][i];

                            traceClinch.Station = csvData["工位号"][i];

                            // 调用存储
                            if (!orderDao.ClinchDataIsSave(traceClinch.TraceId, traceClinch.PointCount, traceClinch.Station))
                                orderDao.SaveClinchData(traceClinch);

                            traceClinchs.Add(traceClinch);
                        }

                        Tools.ProduceLogText($"成功保存{csvData["零件二维码"].Length}条压铆数据，关联码为[{traceClinch.TraceId}],工位[{traceClinch.Station}]");

                        try
                        {
                            // 重命名文件（如果已存在则跳过或覆盖）
                            if (!File.Exists(newFilePath))
                            {
                                File.Move(filePath, newFilePath);

                                //推送压铆工艺数据
                                _ = Task.Run(() => { ViewService.InsertLineMesData(traceClinch.TraceId, traceClinch.Station, traceClinchs); });
                            }
                            else
                            {
                                Tools.ProduceLogTextError($"文件已存在，跳过: {newFileName}");

                                File.Delete(filePath);
                            }
                        }
                        catch (IOException ex)
                        {
                            Tools.ProduceLogTextError($"标签打入失败: {ex.Message}");
                        }
                    }
                }
                catch (DirectoryNotFoundException)
                {
                    Tools.ProduceLogTextError($"压铆数据文件目录不存在: {directory}");
                }
                catch (UnauthorizedAccessException)
                {
                    Tools.ProduceLogTextError("压铆数据文件没有访问权限，请检查凭据。");
                }
                catch (Exception ex)
                {
                    Tools.ProduceLogTextError($"压铆数据文件读取发生错误: {ex.Message}");
                }
            }

            /*using (new NetworkConnection(Path.GetDirectoryName(@"\\192.168.12.55\ym\"), new NetworkCredential("CTOS", "asd")))
            {
                
            }*/
        }

        /// <summary>
        /// 拉铆文件读取
        /// </summary>
        /// <param name="path"></param>
        /// <param name="orderDao"></param>
        private async Task RivetConnection(string pathIp, OrderDao orderDao)
        {
            DateTime now = DateTime.Now;

            int year = now.Year;

            string month = now.Month.ToString().Length > 1 ? now.Month.ToString() : "0" + now.Month.ToString();

            string day = now.Day.ToString().Length > 1 ? now.Day.ToString() : "0" + now.Day.ToString();

            // 初始化文件夹路径
            string directory = $@"\\{pathIp}\data\Data_Info\{year}{month}\{year}{month}{day}";

            if (Directory.Exists(directory))
            {
                try
                {
                    // 获取目录下所有CSV文件路径
                    string[] csvFiles = Directory.GetFiles(directory, "*.csv");

                    foreach (string filePath in csvFiles)
                    {
                        await Task.Delay(10);
                        if (filePath.Contains("_IsSave"))
                            continue;

                        // 提取文件名和扩展名
                        string fileName = Path.GetFileNameWithoutExtension(filePath);
                        string extension = Path.GetExtension(filePath); // 如 ".csv"

                        // 构建新文件名：原文件名 + "_Save" + 扩展名
                        string newFileName = $"{fileName}_IsSave{extension}";
                        string newFilePath = Path.Combine(Path.GetDirectoryName(filePath), newFileName);

                        // 调用方法读取文件数据
                        Dictionary<string, string[]> csvData = await CsvReaderHelper.ReadCsv(filePath, "钉子二维码");

                        List<TraceRivete> traceRivetes = new List<TraceRivete>();

                        // 实例化存储类
                        TraceRivete traceRivete = new TraceRivete();

                        // 循环存储
                        for (int i = 0; i <= csvData["二维码"].Length - 1; i++)
                        {

                            traceRivete.Result = csvData["结果"][i];

                            traceRivete.DataTime = $"{csvData["日期"][i]}";

                            traceRivete.Pulling = csvData["拉力"][i];

                            traceRivete.PullingMax = csvData["拉力上限"][i];

                            traceRivete.PullingMin = csvData["拉力下限"][i];

                            traceRivete.Displacement = csvData["位移"][i];

                            traceRivete.DisplacementMax = csvData["位移上限"][i];

                            traceRivete.DisplacementMin = csvData["位移下限"][i];

                            traceRivete.TraceId = csvData["二维码"][i].Equals("null") ? csvData["批次"][i] : csvData["二维码"][i];

                            traceRivete.PointNo = csvData["点位编号"][i];

                            traceRivete.PointCount = csvData["点位计数"][i];

                            traceRivete.ToolNo = csvData["枪号"][i];

                            traceRivete.Station = csvData["工位"][i];

                            // 调用存储
                            if (!orderDao.RiveteDataIsSave(traceRivete.TraceId, traceRivete.PointCount, traceRivete.Station))
                                orderDao.SaveRiveteData(traceRivete);

                            traceRivetes.Add(traceRivete);
                        }

                        Tools.ProduceLogText($"成功保存{csvData["二维码"].Length}条拉铆数据，关联码为[{traceRivete.TraceId}],工位[{traceRivete.Station}]");

                        try
                        {
                            // 重命名文件（如果已存在则跳过或覆盖）
                            if (!File.Exists(newFilePath))
                            {
                                File.Move(filePath, newFilePath);

                                //推送拉铆工艺数据
                                _ = Task.Run(() => { ViewService.InsertLineMesData(traceRivete.TraceId, traceRivete.Station, traceRivetes); });
                            }
                            else
                            {
                                Tools.ProduceLogTextError($"文件已存在，跳过: {newFileName}");

                                File.Delete(filePath);
                            }
                        }
                        catch (IOException ex)
                        {
                            Tools.ProduceLogTextError($"标签打入失败: {ex.Message}");
                        }
                    }
                }
                catch (DirectoryNotFoundException)
                {
                    Tools.ProduceLogTextError($"拉铆数据文件目录不存在: {directory}");
                }
                catch (UnauthorizedAccessException)
                {
                    Tools.ProduceLogTextError("拉铆数据文件没有访问权限，请检查凭据。");
                }
                catch (Exception ex)
                {
                    Tools.ProduceLogTextError($"拉铆数据文件读取发生错误: {ex.Message}");
                }
            }
            else
            {
                // 文件夹不存在
                Tools.ProduceLogText($"拉铆数据文件夹未生成");
            }
        }
    }
}
